package com.renzhebiao.lkang.token;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.renzhebiao.lkang.exception.ForbiddenException;
import com.renzhebiao.lkang.utils.EmptyTools;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

@Component
public class JwtTokenUtil implements Serializable {

    Logger                      logger                = LoggerFactory.getLogger(JwtTokenUtil.class);
    private static final long   serialVersionUID      = -3301605591108950415L;

    private static final String CLAIM_KEY_USERNAME    = "sub";
    private static final String CLAIM_KEY_PHONE       = "phone";
    private static final String CLAIM_KEY_CREATED     = "created";
    private static final String CLAIM_KEY_ROLE        = "role";
    private static final String CLAIM_KEY_ID          = "userId";
    private static final String CLAIM_KEY_MERCHANT    = "merchantId";
    private static final String CLAIM_KEY_DISTRIBUTOR = "distributorId";
    private static final String CLAIM_KEY_COMPANYID   = "companyId";
    private static final String CLAIM_KEY_SHOPID      = "shopId";
    @Value("${jwt.secret:secret}")
    private String              secret;

    @Value("${jwt.expiration:1000}")
    private Long                expiration;

    // @Autowired
    // private RedisTemplate<String, Object> redisTemplate;
    // @Autowired
    // private JedisPool jedisPool;
    // private Jedis jedis;
    // {
    // jedis=jedisPool.getResource();
    // }
    //
    // @Value("${gate.jwt.prefix}")
    // private String prefix;

    public String getPhoneFromToken(String token) {
        Object username;
        try {
            final Claims claims = getClaimsFromToken(token);
            username = claims.get(CLAIM_KEY_PHONE);// CLAIM_KEY_PHONE
        } catch (Exception e) {
            username = "";
        }
        if (username == null) {
            return "";
        } else {
            return String.valueOf(username);
        }
    }

    public String getUseidFromToken(String token) {
        Object username;
        try {
            final Claims claims = getClaimsFromToken(token);
            username = claims.get(CLAIM_KEY_ID);// CLAIM_KEY_PHONE
        } catch (Exception e) {
            username = "";
        }
        if (username == null) {
            return "";
        } else {
            return String.valueOf(username);
        }
    }

    public Date getCreatedDateFromToken(String token) {
        Date created;
        try {
            final Claims claims = getClaimsFromToken(token);
            created = new Date((Long) claims.get(CLAIM_KEY_CREATED));
        } catch (Exception e) {
            created = null;
        }
        return created;
    }

    public Date getExpirationDateFromToken(String token) {
        Date expiration;
        try {
            final Claims claims = getClaimsFromToken(token);
            expiration = claims.getExpiration();
        } catch (Exception e) {
            expiration = null;
        }
        return expiration;
    }

    public Boolean invalid(String token) {
        // // Jedis jedis = jedisPool.getResource();
        // String username = this.getPhoneFromToken(token);
        // // return redisTemplate.opsForValue().setIfAbsent(username, null);
        // boolean bool = jedis.exists(username);
        // jedis.close();
        return true;
    }

    public Claims getClaimsFromToken(String token) {
        if (EmptyTools.isNullOrEmpty(token)) {
            throw new ForbiddenException(40401, "token无效");
        }
        Claims claims;
        try {
            claims = Jwts.parser().setSigningKey(getSecret()).parseClaimsJws(token).getBody();
        } catch (Exception e) {
            logger.error("解密token错误,错误原因:{}", e.getMessage());
            claims = null;

            // throw new UpBussnissException("解密token错误",e);
        }
        return claims;
    }

    private Date generateExpirationDate() {
        Date date = new Date(System.currentTimeMillis() + expiration * 1000);
        return date;
    }

    public Boolean isTokenExpired(String token) {
        final Date expiration = getExpirationDateFromToken(token);
        if (expiration == null) {
            return true;
        }
        return expiration.before(new Date());
    }

    private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) {
        return (lastPasswordReset != null && created.before(lastPasswordReset));
    }

    // public String generateToken(UserData info) {
    // // Object old = redisTemplate.opsForValue().get(info.phone);
    //
    // String token = "";
    // Map<String, Object> claims = new HashMap<String, Object>();
    // claims.put(CLAIM_KEY_CREATED, new Date());
    // claims.put(CLAIM_KEY_SHOPID, info.shopId);
    // token = generateToken(claims);
    // return token;
    // }

    public String generateToken(Map<String, Object> claims) {

        claims.put(CLAIM_KEY_CREATED, new Date());

        return Jwts.builder().setClaims(claims).setExpiration(generateExpirationDate()).signWith(SignatureAlgorithm.HS512,
                                                                                                 secret).compact();
    }

    public Boolean canTokenBeRefreshed(String token, Date lastPasswordReset) {
        final Date created = getCreatedDateFromToken(token);
        return !isCreatedBeforeLastPasswordReset(created, lastPasswordReset) && !isTokenExpired(token);
    }

    public String refreshToken(String token) {
        // Jedis jedis = jedisPool.getResource();
        //
        // String refreshedToken;
        // try {
        // final Claims claims = getClaimsFromToken(token);
        // claims.put(CLAIM_KEY_CREATED, new Date());
        // refreshedToken = generateToken(claims);
        // // 延长token的有效期
        // // redisTemplate.opsForValue().set(claims.get(CLAIM_KEY_PHONE,String.class), refreshedToken, expiration,
        // // TimeUnit.SECONDS);
        // jedis.setex(claims.get(CLAIM_KEY_PHONE, String.class), expiration.intValue(), refreshedToken);
        // jedis.close();
        // } catch (Exception e) {
        // logger.error("延长token使用时间失败.", e);
        // refreshedToken = null;
        // }
        // return refreshedToken;
        return "token";
    }

    // public Boolean validateToken(String token, UserData info) {
    // Jedis jedis = jedisPool.getResource();
    //
    // if (StringUtils.isBlank(token)) {
    // return false;
    // }
    // // Object existToken = redisTemplate.opsForValue().get(info.getPhone());Jedis
    // Object existToken = jedis.get(info.getPhone());
    // jedis.close();
    // if (token.equals(existToken)) {
    // final String username = getPhoneFromToken(token);
    // final Date created = getCreatedDateFromToken(token);
    // return (username.equals(info.getPhone()) && !isTokenExpired(token));
    // } else {
    // return false;
    // }
    // // if(!token.startsWith(prefix)){
    // // return false;
    // // }else {
    // // token = token.substring(prefix.length() + 1);
    // // }
    // }

    public Boolean validateToken(String token, String phone) {
        if (StringUtils.isBlank(token)) {
            return false;
        }
        // Object existToken = redisTemplate.opsForValue().get(phone);
        // Jedis jedis = jedisPool.getResource();
        // Object existToken = jedis.get(phone);
        // jedis.close();
        // if (token.equals(existToken)) {
        // final String username = getPhoneFromToken(token);
        // final Date created = getCreatedDateFromToken(token);
        // return (username.equals(phone) && !isTokenExpired(token));
        // } else {
        // return false;
        // }
        return true;
    }

    public static void main(String[] args) {
        // BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        // String pwd = encoder.encode("admin");
        // System.out.println(pwd);
        JwtTokenUtil util = new JwtTokenUtil();
        util.setExpiration(1000L);
        util.setSecret("123adsf");
        Map<String, Object> claims = new HashMap<String, Object>();
        // claims.put(CLAIM_KEY_USERID, userInfo.getId());
        claims.put("id", 110);
        String token = util.generateToken(claims);
        Claims myClaims = util.getClaimsFromToken(token);
        Object userId = myClaims.get("id");
        System.out.println(userId);
    }

    public boolean validateInredis(String token) {
        String phone = this.getPhoneFromToken(token);
        // Object tokenInRedis = redisTemplate.opsForValue().get(phone);
        // Jedis jedis = jedisPool.getResource();
        // Object tokenInRedis = jedis.get(phone);
        // jedis.close();
        // if (token.equals(tokenInRedis)) {
        // return true;
        // }
        // return false;
        return true;
    }

    public Long getExpiration() {
        return expiration;
    }

    public void setExpiration(Long expiration) {
        this.expiration = expiration;
    }

    public String getSecret() {
        if (StringUtils.isNotEmpty(this.secret)) {
            return secret;
        }
        return "secret;";
    }

    public void setSecret(String secret) {
        this.secret = secret;
    }

}
